float4x4 World;
float4x4 View;
float4x4 Projection;

texture ModelTexture;
texture NormalMap;
texture GlossMap;
texture NightMap;

float3 LightPos;

sampler2D textureSampler = sampler_state
{
    Texture = (ModelTexture);
    MagFilter = Linear;
    MinFilter = Linear;
    AddressU = Clamp;
    AddressV = Clamp;
};

sampler2D normalSampler = sampler_state
{
    Texture = (NormalMap);
    MagFilter = Linear;
    MinFilter = Linear;
    AddressU = Clamp;
    AddressV = Clamp;
};

sampler2D glossSampler = sampler_state
{
    Texture = (GlossMap);
    MagFilter = Linear;
    MinFilter = Linear;
    AddressU = Clamp;
    AddressV = Clamp;
};

sampler2D nightSampler = sampler_state
{
    Texture = (NightMap);
    MagFilter = Linear;
    MinFilter = Linear;
    AddressU = Clamp;
    AddressV = Clamp;
};

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 TextureCoordinate : TEXCOORD0;
    float3 BiNormal : BINORMAL0;
    float3 Tangent : TANGENT0;
    float3 Normal : NORMAL0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TextureCoordinate : TEXCOORD0;
    float3 LightDir : TEXCOORD1;
    float3 CamView : TEXCOORD2;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    output.TextureCoordinate = input.TextureCoordinate;

    float3x3 worldToTangentSpace;
    worldToTangentSpace[0] = mul(normalize(input.Tangent), World);
    worldToTangentSpace[1] = mul(normalize(input.BiNormal), World);
    worldToTangentSpace[2] = mul(normalize(input.Normal), World);

    output.CamView = normalize(mul(worldToTangentSpace, -viewPosition));
    output.LightDir = normalize(mul(worldToTangentSpace, LightPos - worldPosition));

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float3 ldir = normalize(input.LightDir);
    float3 viewDir = normalize(input.CamView);

    float4 glossColor = tex2D(glossSampler, input.TextureCoordinate).xxxx;

    float3 wnorm = normalize(2.0 * tex2D(normalSampler, input.TextureCoordinate) - 1.0);
    //float3 wnorm = normalize(2.0 * tex2D(normalSampler, float2(input.TextureCoordinate.x, 1.0-input.TextureCoordinate.y)) - 1.0);

    float diffuse = dot(ldir, wnorm);

    float3 ref = reflect(ldir, wnorm);
    float4 specular = pow(saturate(dot(ref, viewDir)), 8);
    specular = specular * glossColor;
    
    if (diffuse < 0.1)
    {
        float4 textureColor = tex2D(nightSampler, input.TextureCoordinate);
        return textureColor;
    }
    else
    {
        float4 textureColor = tex2D(textureSampler, input.TextureCoordinate);
        return (textureColor * diffuse) + specular;
    }
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_3_0 VertexShaderFunction();
        PixelShader = compile ps_3_0 PixelShaderFunction();
    }
}
